package scu.maqiang.mesh;

import java.util.Arrays;

/**
 * 一维两结点线单元
 *
 * @author 马强
 */
public class Mesh1L2 extends Mesh {

    public Mesh1L2() {
        super();
        nDim = 1;
        nPerElement = 2;
        nPerBoundary = 1;
        nEdgePerElement = 1;
        nEdgePerBoundary = 0;
        tecplotType = "FELINESEG";
        nBoundaryPerElement = 2;
        meditMeshType = new String[]{"Vertices", "Edges", "Points"};
        gmshType = new String[]{"SL", "VL", "TL"};
        gmshElementType = 1;
    }

    public Mesh1L2 line(double a, double b, int N) {
        nv = N + 1;
        nt = N;
        nb = 2;
        initMesh0(nv, nt, nb);
        for (int i = 0; i < N + 1; i++) {
            nodes[i] = new double[]{a + (b - a) / N * i};
        }
        for (int i = 0; i < N; i++) {
            elements[i] = new int[]{i, i + 1};
        }
        boundaries[0] = new int[]{0};
        boundaryLabel[0] = 1;
        boundaries[1] = new int[]{N};
        boundaryLabel[1] = 2;
        return this;
    }

    public Mesh1L2 line(double a, double b, int N, double ratio) {
        if (Math.abs(ratio - 1.0) < 1.0e-10) {
            line(a, b, N);
        }
        nv = N + 1;
        nt = N;
        nb = 2;
        initMesh0(nv, nt, nb);

        double texp = 1.0 / (N - 1);
        double alpha = Math.pow(ratio, texp);
        double factor = (1.0 - alpha) / (1 - Math.pow(alpha, N));
        double deltaX = (b - a) * factor;
        nodes[0] = new double[]{a};
        for (int i = 1; i < N + 1; i++) {
            nodes[i] = new double[]{nodes[i - 1][0] + deltaX};
            deltaX *= alpha;
        }
        for (int i = 0; i < N; i++) {
            elements[i] = new int[]{i, i + 1};
        }
        boundaries[0] = new int[]{0};
        boundaryLabel[0] = 1;
        boundaries[1] = new int[]{N};
        boundaryLabel[1] = 2;
        return this;
    }

    @Override
    public boolean checkMesh(double[][] coord) {
        return false;
    }

    public double[] getNodes() {
        double[] result = new double[nv];
        Arrays.setAll(result, i -> nodes[i][0]);
        return result;
    }

    @Override
    public double[] getinteriorPointInElement(double[][] coord) {
        return new double[]{0.5 * (coord[0][0] + coord[1][0])};
    }

    @Override
    public double[] getinteriorPointOnBoundary(double[][] coord) {
        return new double[]{coord[0][0]};
    }

    @Override
    public int[][] getBoundarysFromElement(int i) {
        int[][] boundary = new int[nBoundaryPerElement][];
        int[] ele = elements[i];
        boundary[0] = new int[]{ele[0]};
        boundary[1] = new int[]{ele[1]};
        return boundary;
    }

    @Override
    public int getTecplotNt() {
        return nt;
    }

    @Override
    public int[][] getEdgesFromElement(int i) {
        int[] ele = elements[i].clone();
        return new int[][]{ele};
    }

    public double[] getElementCenter() {
        double[] result = new double[this.nt];
        double[][] coord = new double[nPerElement][nDim];
        for (int i = 0; i < nt; i++) {
            int[] ele = getElement(i);
            getCoordPerElement(ele, coord);
            result[i] = getinteriorPointInElement(coord)[0];
        }
        return result;
    }
}
